const { User, Subscribe } = require("../model"); // requie加载文件时 就会执行加载的js
const { createToken } = require("../util/jwt");
const { promisify } = require("util");
const fs = require("fs");
const lodash = require("lodash");
const rename = promisify(fs.rename);

// 用户路由模块逻辑
const register = async (req, res) => {
  const userModel = new User(req.body);
  const dbJSON = await userModel.save();
  const user = dbJSON.toJSON();
  delete user.password;
  res.status(201).send({ user });
};

//用户注册
const login = async (req, res) => {
  let dbBack = await User.findOne(req.body);
  if (dbBack) {
    dbBack = dbBack.toJSON(); // ?? 暂时没想明白数据库返回的对象还要在 toJSON 一次 ?
    const token = await createToken(dbBack);
    dbBack.token = token;
    res.status(200).json(dbBack);
  } else {
    res.status(402).json({ error: "邮箱或者密码错误!" });
  }
};

//获取用户列表 可以补充分页
const getList = async (req, res) => {
  try {
    const userBack = await User.find();
    res.status(200).json({ data: userBack });
  } catch (error) {
    res.status(500).json({ error });
  }
};

//更新用户信息
const update = async (req, res) => {
  try {
    const id = req.user.userInfo._id;
    const dbBack = await User.findByIdAndUpdate(id, req.body);
    if (dbBack) {
      res.status(200).send({ msg: "修改成功", data: { dbBack }, code: 200 });
    } else res.status(500).send({ msg: "修改失败", code: 500 });
  } catch (error) {
    res.status(500).send({ msg: "修改失败", data: { error }, code: 500 });
  }
};

//上传用户头像
const headimg = async (req, res) => {
  try {
    //从 req.file 可以获取 multer注入的文件的相关信息
    const fileInfo = req.file;
    //重新命名上传文件的名字，由于上传的文件 没有文件后缀名，所以没办法在vscode中预览
    //使用 fs.rename(oldPath,newPath) 重命名
    let fileType = fileInfo.originalname.split(".");
    fileType = fileType[fileType.length - 1];
    const bathPath = "public/";
    rename(
      bathPath + fileInfo.filename,
      bathPath + fileInfo.filename + "." + fileType
    );
    res.status(200).send({
      msg: "上传成功",
      code: 200,
      data: { path: fileInfo.filename + "." + fileType },
    });
  } catch (error) {
    res.status(200).send({ msg: "上传失败", code: 500, data: { error } });
  }
};

//关注 用户/频道
// 整体逻辑: 1.不允许关注自己 2.关注他人时需要添加 自己和被关注的集合到表中 3.被关注的用户subscribeCount值+1
const subscribe = async (req, res) => {
  const userId = req.user.userInfo._id;
  const channelId = req.params.channelId; //获取传入的关注id
  if (userId === channelId) {
    res.status(200).json({ msg: "不能关注自己" });
  }
  try {
    //新建 subscribe数据表 用来存储 关注和被关注者的关系模型
    // user 模型新增被关注数量字段 subscribeCount
    //查找是否有关注过的数据
    const isHaveSubscribe = await Subscribe.findOne({
      user: userId,
      channel: channelId,
    });
    if (!isHaveSubscribe) {
      //未关注将数据保存 并 将被关注的人的被关注数量+1
      await new Subscribe({ user: userId, channel: channelId }).save();
      //查询User表中被关注人的信息进行+1
      const user = await User.findById(channelId);
      user.subscribeCount++;
      await new User(user).save();
      res.status(200).json({ msg: "关注成功!!" });
    } else {
      res.status(400).json({ msg: "已经关注过了!" });
    }
  } catch (error) {
    res.status(400).json({ error });
  }
};

//取消关注 用户/频道
// 整体逻辑: 1.不允许取消自己 2.取消他人时需要删除 自己和被关注的集合表中 3.被关注的用户subscribeCount值-1
const unsubscribe = async (req, res) => {
  const userId = req.user.userInfo._id;
  const channelId = req.params.channelId; //获取传入的关注id
  if (userId === channelId) {
    res.status(200).json({ msg: "不能取消自己" });
  }
  try {
    //新建 subscribe数据表 用来存储 关注和被关注者的关系模型
    // user 模型新增被关注数量字段 subscribeCount
    //查找是否有关注过的数据
    const isHaveSubscribe = await Subscribe.findOne({
      user: userId,
      channel: channelId,
    });
    if (isHaveSubscribe) {
      isHaveSubscribe.remove(); //取消关注 从表中删除这条记录
      //查询User表中被关注人的信息进行+1
      const user = await User.findById(channelId);
      user.subscribeCount--;
      await new User(user).save();
      res.status(200).json({ msg: "取消关注成功!!" });
    } else {
      res.status(400).json({ msg: "还没有关注过!" });
    }
  } catch (error) {
    res.status(400).json({ error });
  }
};

// 1.判断是否登录 2.查找是否关注过 3.查找user表相关详情并将是否关注过的状态一起返回
const getusers = async (req, res) => {
  if (req.user) {
    //有user则为登录郭 ps:登录校验时会注入user到req
    try {
      let isSubscribe = false;
      let isExit = await Subscribe.findOne({
        user: req.user.userInfo._id,
        channel: req.params.channelId,
      });
      isSubscribe = isExit ? true : false; //是否关注过
      let tarUser = await User.findById(req.params.channelId);
      console.log(tarUser, "=== tarUser ===");

      let backObj = {
        ...lodash.pick(tarUser, [
          "username",
          "email",
          "phone",
          "image",
          "channeldes",
          "subscribeCount",
        ]),
        isSubscribe,
      }; // lodash的pick方法重新返回需要哪些参数的对象
      res.status(200).json({ backObj });
    } catch (error) {
      res.status(500).json({ error });
    }
  }
};


// 获取用户关注的所有 用户/频道相关信息
const getsubscribe = async (req, res) => {
  try {
    let dbBack = await Subscribe.find({
      user: req.params.userId,  //获取的是用户关注了其它的用户只需要查询该用户或频道的 user的id即可
    }).populate("channel")  // 使用populate联表查询User表，并将所有的数据返回给channel字段
    let scribeList = dbBack.map((item) => {
      return lodash.pick(item.channel, ['_id','username','phone','email','channeldes']) //使用lodash pick过滤需要的字段
    });
    res.status(200).json({data:scribeList})
  } catch (error) {
    res.status(500).json({error})
  }
};

// 获取某用户的所有粉丝
const getchannels = async (req,res)=>{
  try {
    let dbBack = await Subscribe.find({
      channel:req.user.userInfo._id  //获取的是用户或频道 的粉丝，所以只需要查询 channel的id即可。
    }).populate('user')
    let scribeList = dbBack.map((item) => {
      return lodash.pick(item.user, ['_id','username','phone','email','channeldes']) //使用lodash pick过滤需要的字段
    });
    res.status(200).json({data:scribeList})
  } catch (error) {
    res.status(500).json({error})
  }
}

module.exports = {
  register,
  login,
  getList,
  update,
  headimg,
  subscribe,
  unsubscribe,
  getusers,
  getsubscribe,
  getchannels
};
